package com.cxq.boot.service;

import com.cxq.boot.dto.CommentDTO;
import com.cxq.boot.enums.CommentTypeEnum;
import com.cxq.boot.enums.NotificationStatusEnum;
import com.cxq.boot.enums.NotificationTypeEnum;
import com.cxq.boot.exception.CustomizeErrorCode;
import com.cxq.boot.exception.CustomizeException;
import com.cxq.boot.mapper.*;
import com.cxq.boot.model.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CommentService {

    @Autowired
    private UserMapper userMapper;//用户
    @Autowired
    private QuestionMapper questionMapper;//问题
    @Autowired
    private QuestionExtMapper questionExtMapper;//额外问题
    @Autowired
    private CommentMapper commentMapper;//评论
    @Autowired
    private CommentExtMapper commentExtMapper;//额外评论
    @Autowired
    private NotificationMapper notificationMapper;//通知

    @Transactional //开启事务，使整个方法体加上事务
    public void insert(Comment comment, User commentator) {
        if (comment.getParentId() == null || comment.getParentId() == 0) {
            throw new CustomizeException(CustomizeErrorCode.TARGET_PARAM_NOT_FOUND);
        }
        if (comment.getType() == null || !CommentTypeEnum.isExist(comment.getType())) {
            throw new CustomizeException(CustomizeErrorCode.TYPE_PARAM_WRONG);
        }
        if (comment.getType() == CommentTypeEnum.COMMENT.getType()) {
            //回复评论
            Comment dbComment = commentMapper.selectByPrimaryKey(comment.getParentId());//找到评论的评论
            if (dbComment == null) {
                throw new CustomizeException(CustomizeErrorCode.COMMENT_NOT_FOUND);
            } else {

                //该评论的回复的问题，由此知道通知的消息title都是问题title，不适用评论title
                Question dbQuestion = questionMapper.selectByPrimaryKey(dbComment.getParentId());//找到评论的问题
                if (dbQuestion == null) {
                    throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
                }

                commentMapper.insert(comment);
                //增加评论数
                /*Comment parentComment = new Comment();
                parentComment.setParentId(comment.getParentId());
                parentComment.setCommentCount(1);
                commentExtMapper.incCommentCount(parentComment);*/

                dbComment.setCommentCount(1);
                commentExtMapper.incCommentCount(dbComment);

                //创建通知
                createNotify(comment, dbComment.getCommentator(), commentator.getName(), dbQuestion.getTitle(), NotificationTypeEnum.REPLY_COMMENT, dbComment.getParentId());
            }
        } else {
            //回复问题
            Question dbQuestion = questionMapper.selectByPrimaryKey(comment.getParentId());
            if (dbQuestion == null) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            } else {
                comment.setCommentCount(0);//数据库默认可能失效，可以使用insertSelective默认值就有效
                commentMapper.insert(comment);
                //增加评论数
                dbQuestion.setCommentCount(1);
                questionExtMapper.incCommentCount(dbQuestion);

                //创建通知
                createNotify(comment, dbQuestion.getCreator(), commentator.getName(), dbQuestion.getTitle(), NotificationTypeEnum.REPLY_QUESTION, dbQuestion.getId());
            }
        }
    }

    private void createNotify(Comment comment, Long receiver, String notifierName, String outerTitle, NotificationTypeEnum notificationType, Long outerId) {
        //通知人和评论人相同时，不通知
        if (receiver.equals(comment.getCommentator())){
            return;
        }
        Notification notification = new Notification();
        notification.setGmtCreate(System.currentTimeMillis());
        notification.setType(notificationType.getType());//通知类型
        notification.setStatus(NotificationStatusEnum.UNDEAD.getStatus());//通知阅读状态
        notification.setNotifier(comment.getCommentator());//通知人
        notification.setOuterId(outerId);//通知的评论或问题
        notification.setReceiver(receiver);//接收人
        notification.setNotifierName(notifierName);//通知人名
        notification.setOuterTitle(outerTitle);//通知的评论或问题title
        notificationMapper.insert(notification);
    }

    public List<CommentDTO> listByQuestionId(Long id, CommentTypeEnum type) {
        //获取这个问题id的所有评论
        CommentExample commentExample = new CommentExample();
        commentExample.createCriteria()
                .andParentIdEqualTo(id)
                .andTypeEqualTo(type.getType());
        commentExample.setOrderByClause("gmt_Create desc");//设置排序，写入SQL语句
        List<Comment> comments = commentMapper.selectByExample(commentExample);

        if (comments.size() == 0) {
            return new ArrayList<>();
        }

        //获取去重的评论人
        Set<Long> commentators = comments.stream().map(comment -> comment.getCommentator()).collect(Collectors.toSet());
        //将其转换成userId
        List<Long> userIds = new ArrayList<>();
        userIds.addAll(commentators);

        //查询评论人用户信息
        UserExample userExample = new UserExample();
        userExample.createCriteria()
                .andIdIn(userIds);
        List<User> users = userMapper.selectByExample(userExample);
        //将用户id和用户映射成map
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(user -> user.getId(), user -> user));

        //将评论和用户封装到CommentDTO返回
        List<CommentDTO> commentDTOS = comments.stream().map(comment -> {
            CommentDTO commentDTO = new CommentDTO();
            BeanUtils.copyProperties(comment, commentDTO);
            commentDTO.setUser(userMap.get(comment.getCommentator()));
            return commentDTO;
        }).collect(Collectors.toList());

        return commentDTOS;
    }
}
